#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "ListIter.h"

/***************************************************************************************************************/
/**********************************    struct Node & struct List    ********************************************/
/***************************************************************************************************************/
typedef struct Node_t
{
    void*           data;
    struct Node_t*  next;       /*  Pointer to next */
    struct Node_t*  prev;       /*  Pointer to prev */
}Node;

struct List_t
{
    Node head;
    Node tail;
};
/**************************************************************************************************************/

List* ListNew(void)
{
    List* list= (List*)malloc(sizeof(List));

    if(!list)
    {
        fprintf(stderr, "List not created");
        return 0;
    }

    list->head.prev = (void*)0xdeadbeef;
    list->tail.next = (void*)0xdeadbeef;
    list->head.next = &(list->tail);
    list->tail.prev = &(list->head);
    list->head.data = (void*)0xdeadbeef;
    list->tail.data = (void*)0xdeadbeef;

    return list;
}


void ListDelete(List* _list)
{
    Node* node;
    assert(_list);

    node = _list->head.next;
    while(node != &_list->tail)
    {
        node = node->next;
        free(node->prev);
    }
    free(_list);
}


Iter ListInsert(Iter _it, void* _data)
{
    Node* node;

    assert(_it);
    node = (Node*)malloc(sizeof(Node));
    node->data      = _data             ;
    node->prev      = ((Node*)_it)->prev;           /*  The prev of new is front            */
    node->next      = (Node*)_it        ;           /*  the next of new is the front next   */
    ((Node*)_it)->prev->next  = node    ;
    ((Node*)_it)->prev        = node    ;

    return (Iter)node;
}

Iter ListBegin(List* _list)
{
    assert(_list);
    return (Iter)_list->head.next;
}


Iter ListEnd(List* _list)
{
    assert(_list);
    return (Iter)&_list->tail;
}


int ListIsEmpty(List* _list)
{
    assert(_list);
    return _list->head.next == &_list->tail;
}


void* ListGetData(Iter _it)
{
    assert(_it);
    return ((Node*)_it)->data;
}


Iter ListNext(Iter _it)
{
    assert(_it);
    return (Iter)((Node*)_it)->next;
}


Iter ListPrev(Iter _it)
{
    assert(_it);
    return (Iter)((Node*)_it)->prev;
}


Iter ListRemove(Iter _it)
{
    Node* nextNode;

    assert(_it);
    nextNode = ((Node*)_it)->next;
    ((Node*)_it)->next->prev = ((Node*)_it)->prev;              /*  The "After the removed" prev is front   */
    ((Node*)_it)->prev->next = ((Node*)_it)->next;              /*  Also update the next of front           */
    free((Node*)_it);

    return (Iter)nextNode;
}

int ListIterIsEqual(Iter _it1, Iter _it2)
{
    assert(_it1 && _it2);

    return (Node*)_it1 == (Node*)_it2;
}


size_t  ListCount(List* _list)
{
    Node*   node        ;
    size_t  count = 0   ;

    assert(_list);

    node = _list->head.next;
    while(node != &_list->tail)
    {
        ++count;
        node = node->next;
    }
    return count;
}
